package org.poem.controller;


import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.poem.CommonVO;
import org.poem.IdsVo;
import org.poem.databases.redis.ContextRedisUtils;
import org.poem.datasource.*;
import org.poem.datasource.table.TableVO;
import org.poem.entity.TDatasource;
import org.poem.id.SnowFlake;
import org.poem.result.CommonResult;
import org.poem.result.PageableResult;
import org.poem.service.ITDataSourceConfigService;
import org.poem.service.ITDataSourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 数据源 前端控制器
 * </p>
 *
 * @author vinshine
 * @since 2019-10-24
 */
@Controller
@RequestMapping("/v1/tDataSource")
@Slf4j
@Api(tags = {"02-数据源接口"})
public class TDataSourceController {

    @Autowired
    ITDataSourceService itDataSourceService;

    @Autowired
    ITDataSourceConfigService itDataSourceConfigService;


    @Autowired
    private ContextRedisUtils redisUtils;

    /**
     * Integer正则表达式 ^-?(([1-9]\d*$)|0)
     */
    private static final String INTEGER = "^([1-9]\\d[2-5]$)";


    @ApiOperation(value = "0200_获取数据库列表", notes = "获取数据库列表")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @GetMapping("/getAllDatasourceList")
    @ResponseBody
    public CommonResult<List<CommonVO>> getAllDatasourceList(){
        List<TDatasource> list = itDataSourceService.list();
        List<CommonVO> commonVOS =  list.parallelStream().map(
                 o->{
                     CommonVO commonVO = new CommonVO();
                     commonVO.setId(o.getId()+"");
                     commonVO.setName(o.getName());
                     return commonVO;
                 }
         ).collect(Collectors.toList());
        return new CommonResult<>(commonVOS);
    }
    /**
     * 01-展示数据源管理+分页
     *
     * @param pageSize   分页大小
     * @param pageNumber 页数
     * @return
     */
    @ApiOperation(value = "0201_展示数据源管理-带有分页", notes = "展示数据源管理")
    @ApiResponses
            ({
                    @ApiResponse(code = 400, message = "请求参数没有填好"),
                    @ApiResponse(code = 404, message = "请求路径没有找到")
            })
    @GetMapping("/findDataSourceList/{size}/{number}")
    @ResponseBody
    public CommonResult<PageableResult<DataSourceVo>> findDataSourceList(String sourceName,
                                                                         @PathVariable("size") Integer pageSize,
                                                                         @PathVariable("number") Integer pageNumber) {
        DataSourceQueryVo dataSourceQueryVo = new DataSourceQueryVo();
        dataSourceQueryVo.setSourceName(sourceName);
        log.info("TDataSourceController:findDataSourceList:[dataSourceQueryVo]:" + JSONObject.toJSONString(dataSourceQueryVo) + "  [pageSize]:" + pageSize + ", [pageNumber]: " + pageNumber);
        PageableResult<DataSourceVo> dataSourceList = itDataSourceService.findDataSourceList(dataSourceQueryVo, pageSize, pageNumber);
        return new CommonResult<>(dataSourceList);
    }

    /**
     * 02-新建数据源+新增参数
     *
     * @param dataSourceVo
     * @return
     */
    @ApiOperation(value = "0202_新建数据源", notes = "新建数据源")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/addDataSource")
    @ResponseBody
    public CommonResult<String> addDataSource(@RequestBody DataAndParametersVo dataSourceVo) {
        log.info("TDataSourceController:addDataSource:[dataSourceVo]:" + JSONObject.toJSONString(dataSourceVo));
        String s = "";
        Long dataSourceId = SnowFlake.genLongId();
        try {
            this.itDataSourceService.testDataSource(dataSourceVo);
        } catch (CanalClientException | org.poem.exception.CanalClientException e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return new CommonResult<>(1, e.getMessage());
        }
        try {
            if (null != dataSourceVo.getDataSourceVo()) {
                DataSourceVo dataSource = dataSourceVo.getDataSourceVo();

                dataSource.setId(dataSourceId);
                s = itDataSourceService.addDataSource(dataSource, dataSourceId);
            }

            //如果集合大于0，说明用户传入了参数
            if (dataSourceVo.getParametersVos().size() > 0) {
                //获取用户传过来的参数集合
                List<ParametersVo> parametersVos = dataSourceVo.getParametersVos();
                List<DataSourceConfigVo> list = new ArrayList<>();
                for (ParametersVo parametersVo : parametersVos) {
                    DataSourceConfigVo dataSourceConfigVo = new DataSourceConfigVo();
                    dataSourceConfigVo.setValue(parametersVo.getValue());
                    dataSourceConfigVo.setName(parametersVo.getName());
                    list.add(dataSourceConfigVo);
                }

                s = itDataSourceConfigService.addOrUpdateDataSourceParameters(list, dataSourceId);
            }
            return new CommonResult<>(0, null, "成功！");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new CommonResult<>(1, null, s);
    }

    /**
     * 03-根据数据源id查询数据源详情
     *
     * @param dataSourceId 数据源id
     * @return
     */
    @ApiOperation(value = "0203_根据id查询数据源详情", notes = "根据id查询数据源详情")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @GetMapping("/getDataSourceVoById/{dataSourceId}")
    @ResponseBody
    public CommonResult<DataAndParametersVo> getDataSourceVoById(@PathVariable("dataSourceId") Long dataSourceId) {
        log.info("TDataSourceController:getDataSourceVoById:dataSourceId" + dataSourceId);
        //获取数据源
        DataSourceVo dataSource = itDataSourceService.getDataSourceVoById(dataSourceId);
        //查询数据源参数
        List<DataSourceConfigVo> dataSourceConfigVo = itDataSourceConfigService.getDataSourceParametersVo(dataSourceId);
        List<ParametersVo> parametersVos = new ArrayList<>();  //所有参数
        for (DataSourceConfigVo sourceParametersVo : dataSourceConfigVo) {
            ParametersVo parametersVo = new ParametersVo();
            parametersVo.setName(sourceParametersVo.getValue());
            parametersVo.setValue(sourceParametersVo.getName());
            parametersVos.add(parametersVo);
        }
        //将基本信息和参数放进去
        DataAndParametersVo dataAndParametersVo = new DataAndParametersVo();
        dataAndParametersVo.setDataSourceVo(dataSource);
        dataAndParametersVo.setParametersVos(parametersVos);
        return new CommonResult<>(dataAndParametersVo);
    }

    /**
     * 04-修改数据源
     *
     * @param dataSourceVo
     * @return
     */
    @ApiOperation(value = "0204_修改数据源", notes = "修改数据源")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/updateDataSource")
    @ResponseBody
    public CommonResult<String> updateDataSource(@RequestBody DataAndParametersVo dataSourceVo) {
        log.info("TDataSourceController:updateDataSource:" + JSON.toJSONString(dataSourceVo));
        try {
            this.itDataSourceService.testDataSource(dataSourceVo);
        } catch (CanalClientException | org.poem.exception.CanalClientException e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return new CommonResult<>(1, e.getMessage());
        }
        //数据源的配置
        DataSourceVo dataSource = dataSourceVo.getDataSourceVo();
        String s = itDataSourceService.updateDataSource(dataSource);
        //数据源的基本参数
        if (dataSourceVo.getParametersVos().size() > 0) {
            List<ParametersVo> parametersVos = dataSourceVo.getParametersVos();
            List<DataSourceConfigVo> list = new ArrayList<>();
            for (ParametersVo parametersVo : parametersVos) {
                DataSourceConfigVo dataSourceConfigVo = new DataSourceConfigVo();
                dataSourceConfigVo.setValue(parametersVo.getValue());
                dataSourceConfigVo.setName(parametersVo.getName());
                list.add(dataSourceConfigVo);
            }
            Long id = dataSourceVo.getDataSourceVo().getId();
            //获取当前用户
            s = itDataSourceConfigService.addOrUpdateDataSourceParameters(list, id);
        }
        return new CommonResult<>(0, null, s);
    }

    /**
     * 05-根据数据源id删除数据源
     *
     * @param dataSourceId 数据源id
     * @return
     */
    @ApiOperation(value = "0205_根据数据源id删除数据源", notes = "根据数据源id删除数据源")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/deleteDataSourceById")
    @ResponseBody
    public CommonResult<String> deleteDataSourceById(Long dataSourceId) {
        log.info("TDataSourceController:deleteDataSourceById:dataSourceId=" + dataSourceId);
        String s = "";
        try {
            s = itDataSourceService.deleteDataSourceById(dataSourceId);
            s = itDataSourceConfigService.deleteDataSourceParametersById(dataSourceId);
            return new CommonResult<>(0, null, "删除成功！");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new CommonResult<>(1, null, "删除失败！");
    }

    /**
     * 06-根据数据源id批量删除
     *
     * @param idsVo 数据源id数组
     * @return
     */
    @ApiOperation(value = "0206_根据数据源id批量删除除", notes = "根据数据源id批量删除")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/deleteDataSource")
    @ResponseBody
    public CommonResult<String> deleteDataSource(@RequestBody IdsVo idsVo) {
        Long[] ids = idsVo.getIds();
        log.info("TDataSourceController:deleteDataSource:ids" + ids.toString());
        String s = itDataSourceService.deleteDataSource(idsVo);
        return new CommonResult<>(0, null, s);
    }

    /**
     * 10-数据源测试连接
     *
     * @param dataSourceVo
     * @return
     */
    @ApiOperation(value = "2010_数据源测试连接", notes = "数据源测试连接")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/testDataSourceConnect")
    @ResponseBody
    public CommonResult<String> testDataSourceConnect(@RequestBody DataAndParametersVo dataSourceVo) {
        log.info("CDataSourceController:testDataSourceConnect:[dataSourceVo]:" + JSONObject.toJSONString(dataSourceVo));
        try {
            this.itDataSourceService.testDataSource(dataSourceVo);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return new CommonResult<>(1, e.getMessage());
        }
        return new CommonResult<>(0, null, "链接正确.");
    }



    /**
     * 12-从Redis获取连接池信息
     *
     * @return
     */
    @ApiOperation(value = "0212_从Redis获取连接池信息", notes = "从Redis获取连接池信息")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @GetMapping("/getRedisConnectionPoolVo{dataSourceId}")
    @ResponseBody
    public CommonResult<ConnectionPoolVo> getRedisConnectionPoolVo(@PathVariable("dataSourceId") Long dataSourceId) {
        DruidDataSource druidDataSource = (DruidDataSource) redisUtils.get(dataSourceId + "");

        druidDataSource.getDbType();
        //获取到活动数
        int activeCount = druidDataSource.getActiveCount();
        //获取最大活动数
        int maxActive = druidDataSource.getMaxActive();
        //获取最小空闲数
        int minIdle = druidDataSource.getMinIdle();
        //获取到最大空闲数
        int maxIdle = druidDataSource.getMaxIdle();
        ConnectionPoolVo connectionPoolVo = new ConnectionPoolVo();
        connectionPoolVo.setActiveCount(activeCount);
        connectionPoolVo.setMaxActive(maxActive);
        connectionPoolVo.setMinIdle(minIdle);
        connectionPoolVo.setMaxIdle(maxIdle);

        return new CommonResult<>(null);
    }

    /**
     * 13-从Redis获取连接池信息
     *
     * @return
     */
    @ApiOperation(value = "0214_获取数据源的列表", notes = "从Redis获取连接池信息")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @GetMapping("/getDatasourceList/{subjectId}")
    @ResponseBody
    public CommonResult<List<CommonVO>> getDatasourceList(@PathVariable("subjectId") Long subjectId) {
        log.info("CDataSourceController:getDatasourceList:subjectId:" + subjectId);
        List<CommonVO> commonVOS = itDataSourceService.getDatasourceList(subjectId);
        return new CommonResult<>(commonVOS);
    }


    /**
     * 10-数据源测试连接
     *
     * @param dataSourceVo
     * @return
     */
    @ApiOperation(value = "0215_获取数据库信息", notes = "获取数据库信息")
    @ApiResponses({
            @ApiResponse(code = 400, message = "请求参数没有填好"),
            @ApiResponse(code = 404, message = "请求路径没有找到")
    })
    @PostMapping("/getSchema")
    @ResponseBody
    public CommonResult<List<String>> getSchema(@RequestBody DataAndParametersVo dataSourceVo) {
        log.info("CDataSourceController:getSchema:[dataSourceVo]:" + JSONObject.toJSONString(dataSourceVo));
        List<String> schema = this.itDataSourceService.getSchema(dataSourceVo);
        return new CommonResult<>(0, schema, "链接正确.");
    }

    /**
     * 根据id查询任务信息
     *
     * @param datasourceId 计算的id
     * @return
     */
    @ApiOperation(value = "0705-根据id查询任务信息", notes = "根据id查询任务信息")
    @ApiResponses({@ApiResponse(code = 400, message = "请求参数没有填好"), @ApiResponse(code = 404, message = "请求路径没有找到")})
    @GetMapping(value = "/getDatabaseBySourceId/{datasourceId}")
    @ResponseBody
    public CommonResult<List<TableVO>> getDatabaseBySourceId(@PathVariable("datasourceId") String datasourceId) {
        log.info("TaskController-getTaskById:[id]:" + JSONObject.toJSONString(datasourceId));
        if (StringUtils.isEmpty(datasourceId)) {
            return new CommonResult<>(1, null, "datasourceId can\'t be empty.");
        }
        List<TableVO> schemaVOS = this.itDataSourceService.getDatabaseBySourceId(datasourceId);
        return new CommonResult<>(schemaVOS);
    }
}
